<?
/**
 * Session for sending API requests to a service supported
 * by the Large Merchant Services Platform.
 * 
 * As of the writing of this documentation this includes:
 * (1) Bulk Data Exchange Service (BDX)
 * (2) File Transfer Service (FTS) 
 */
class LargeMerchantServiceParser extends gravy{

	public function __construct(){
		parent::__construct();
	}

	public function unzipFile($zipFile,$location,$deleteZipOnSuccess=true){
		$result=false;
		$this->debug("Unzipping $zipFile to $location.",$list);
		if(file_exists($zipFile)){
			$this->debug("File ($zipFile) exists...");
			$zip=zip_open($zipFile);
			if(is_resource($zip)){
				$this->debug("Zip is a resource.");
				while($zip_entry=zip_read($zip)){
					$this->debug("Found Zip Entry.",zip_entry_name($zip_entry));
					if(file_put_contents($location.zip_entry_name($zip_entry),zip_entry_read($zip_entry,zip_entry_filesize($zip_entry)))){
						$result=$location.zip_entry_name($zip_entry);
						$this->debug("Unzipped Entry: ".zip_entry_name($zip_entry).".",$result);
						if(file_exists($result)){
							touch($result);
							$this->debug("Entry now exists on the filesystem (".filesize($result)."B).");
						}else{
							$this->addCustomError("0xZIP1403","Error unzipping file","The unzipped file (\"".$location.zip_entry_name($zip_entry)."\") was not found on the filesystem.");
							$result=false;
						}
					}else{
						$this->addCustomError("0xZIP1402","Error unzipping file","An error occurred while trying to decompress the file \"".$location.zip_entry_name($zip_entry)."\".");
					}
				}
			}else{
				$this->addCustomError("0xZIP1401","Error unzipping file","The file $zipFile does not appear to be a ZIP file.");
			}
		}else{
			$this->addCustomError("0xZIP1400","Error unzipping file","The file $zipFile does not exist on this server.");
		}
		if($result&&$deleteZipOnSuccess){
			$this->debug("Removing zip file.");
			if(unlink($zipFile)){
				$this->debug("Deleted the zip file.");
			}
		}
		return($result);
	}

	//Good Pull Parsing example: http://www.ibm.com/developerworks/xml/library/x-xmlphp2.html.
	public function validateLmsFile($inputFile,$outputFile){
		$result=false;
		$decRead=false;
		$rootRead=false;
		$reader=fopen($inputFile,"r");
		$limit=15000000;
		if($reader){
			$writer=fopen($outputFile,"w");
			if($writer){
				$c=0;
				 print("<h1>Outfile Created: ".$outputFile."</h1>");
				while(($buffer=fgets($reader,4096))!==false){
					if($c==0){
						print("<h1>OK - Pulled the First Line.</h1>");
					}
					if($c>$limit){
						print("<h1>Breaking!</h1>");
						break;
					}
					$c++;
					$writeLine=true;
					if(preg_match("/\<\?xml/",$buffer)>0){
						if($decRead){
							$writeLine=false;
						}
						$decRead=true;
					}
					if(preg_match("/\<BulkData/",$buffer)>0){
						if($rootRead){
							$writeLine=false;
						}
						$rootRead=true;
					}
					if($writeLine){
						fwrite($writer,$buffer);
					}
				}
				print("<h1>The result is GOOD for validateLmsFile(\"$inputFile\",\"$outputFile\")</h1>");
				$result=true;
				fclose($writer);
			}
			fclose($reader);
		}
		return($result);
	}

	public function quoteString($str){
		return("\"".preg_replace("/\"/","\"\"",$str)."\"");
	}

	public function getSoldReportRow(){
		return(
			array(
				"OrderID"=>"",
				"BuyerUserID"=>"",
				"BuyerFirstName"=>"",
				"BuyerLastName"=>"",
				"BuyerEmail"=>"",
				"BuyerPhone"=>"",
				"ShipRecipientName"=>"",
				"ShipStreet1"=>"",
				"ShipStreet2"=>"",
				"ShipCityName"=>"",
				"ShipStateOrProvince"=>"",
				"ShipPostalCode"=>"",
				"ShipCountryName"=>"",
				"ShippingService"=>"",
				"PaymentClearedTime"=>"",
				"CheckoutSiteID"=>"",
				"OrderCreationTime"=>"",
				"InsuranceCost"=>"",
				"ShippingCost"=>"",
				"OrderTotalCost"=>"",
				"ItemID"=>"",
				"SKU"=>"",
				"QuantitySold"=>"",
				"SalePrice"=>"",
				"TaxAmount"=>"",
				"TotalCost"=>"",
				"ListingSiteID"=>"",
				"SellingManagerSaleRecordID"=>"",
				"BuyerPaymentTransactionNumber"=>""
			)
		);
	}

	public function getSaleOrderLineFromRow($row){
		$result=false;
		if(strlen($row["OrderID"])>0){
			$result="";
			$tmp=preg_split("/\-/",$row["OrderID"]);
			$result.=$tmp[1].",";
			$result.=$this->quoteString($row["BuyerUserID"]).",";
			$result.=$this->quoteString($row["BuyerFirstName"]).",";
			$result.=$this->quoteString($row["BuyerLastName"]).",";
			$result.=$this->quoteString($row["BuyerEmail"]).",";
			$result.=$this->quoteString($row["BuyerPhone"]).",";
			$result.=$this->quoteString($row["ShipRecipientName"]).",";
			$result.=$this->quoteString($row["ShipStreet1"]).",";
			$result.=$this->quoteString($row["ShipStreet2"]).",";
			$result.=$this->quoteString($row["ShipCityName"]).",";
			$result.=$this->quoteString($row["ShipStateOrProvince"]).",";
			$result.=$this->quoteString($row["ShipPostalCode"]).",";
			$result.=$this->quoteString($row["ShipCountryName"]).",";
			$result.=strtotime($row["PaymentClearedTime"]).",";
			$result.=$row["CheckoutSiteID"].",";
			$result.=$row["InsuranceCost"].",";
			$result.=$row["ShippingCost"].",";
			$result.=$row["OrderTotalCost"].",";
			$result.=$this->quoteString($row["ItemID"]).",";
			$result.=$this->quoteString($row["SKU"]).",";
			$result.=((int)$row["QuantitySold"]).",";
			$result.=$row["SalePrice"].",";
			$result.=$row["TaxAmount"].",";
			$result.=$row["TotalCost"].",";
			$result.=((int)$row["ListingSiteID"]).",";
			$result.=((int)$row["SellingManagerSaleRecordID"]).",";
			$result.=$this->quoteString($row["BuyerPaymentTransactionNumber"])."\n";
		}
		return($result);
	}

	//Good Pull Parsing example: http://www.ibm.com/developerworks/xml/library/x-xmlphp2.html.
	public function convertSoldReportToImportFile($inputFile,$outputFile){
		$result=false;
		$reader=new XMLReader();
		$limit=500;
		$c=0;
		$orderFound=false;
		$reader->open($inputFile);
		$row=$this->getSoldReportRow();
		$kill=false;
		if($handle=fopen($outputFile,"w")){
			while($reader->read()){
				switch($reader->nodeType){
					case(XMLREADER::ELEMENT):
						$keys=array_keys($row);
	//					print("Is ".$reader->localName." equal to OrderID.<br />");
						$nodeName=$reader->localName;
						if($nodeName=="OrderID"){
							$row=$this->getSoldReportRow();
						}
						if(in_array($nodeName,$keys)){
							$reader->read();
							$row[$nodeName]=$reader->value;
	//						print("<pre>");
	//						print_r($row);
	//						print("</pre>");
						}elseif($reader->localName=="OrderDetails"){
							if($orderFound){
								if($line=$this->getSaleOrderLineFromRow($row)){
									if(fwrite($handle,$line)===FALSE){
										$kill=true;
									}
								}
							}
							$orderFound=true;
						}
						break;
				}
				if($kill){
					break;
				}
				$c++;
			}
			if($line=$this->getSaleOrderLineFromRow($row)){
				fwrite($handle,$line);
			}
			fclose($handle);
		}
		return($result);
	}

	public function getActiveInventoryReportRow(){
		return(
			array(
				"SKU"=>"",
				"Price"=>"",
				"Quantity"=>"",
				"ItemID"=>"",
				"BidCount"=>"",
				"ReserveMet"=>""
			)
		);
	}

	public function getActiveInventoryReportLineFromRow($row){
		$result=false;
		if(strlen($row["ItemID"])>0){
			$result="";
			$result.=(int)$row["BidCount"].",";
			$result.=$this->quoteString($row["ItemID"]).",";
			$result.=(double)$row["Price"].",";
			$result.=(int)$row["Quantity"].",";
			$result.=(int)$row["ReserveMet"].",";
			$result.=$this->quoteString($row["SKU"])."\n";
		}
		return($result);
	}

	//Good Pull Parsing example: http://www.ibm.com/developerworks/xml/library/x-xmlphp2.html.
	public function convertActiveInventoryReportToImportFile($inputFile,$outputFile){
		$result=false;
		$tmpFile=realpath(dirname($inputFile))."/".rand(0,999999).".tmp";
		$this->validateLmsFile($inputFile,$tmpFile);
//		@unlink($inputFile);
		$inputFile=$tmpFile;
		$reader = new XMLReader();
		$limit=500;
		$c=0;
		$orderFound=false;
		$reader->open($inputFile);
		$row=$this->getActiveInventoryReportRow();
		$kill=false;
		if($handle=fopen($outputFile,"w")){
			while($reader->read()){
				switch($reader->nodeType){
					case(XMLREADER::ELEMENT):
						$keys=array_keys($row);
	//					print("Is ".$reader->localName." equal to OrderID.<br />");
						$nodeName=$reader->localName;
						if($nodeName=="SKU"){
							$row=$this->getActiveInventoryReportRow();
						}
						if(in_array($nodeName,$keys)){
							$reader->read();
							$row[$nodeName]=$reader->value;
	//						print("<pre>");
	//						print_r($row);
	//						print("</pre>");
						}elseif($reader->localName=="SKUDetails"){
							if($orderFound){
								if($line=$this->getActiveInventoryReportLineFromRow($row)){
									if(fwrite($handle,$line)===FALSE){
										$kill=true;
									}
								}
							}
							$orderFound=true;
						}
						break;
				}
				if($kill){
					break;
				}
				$c++;
			}
			if($line=$this->getActiveInventoryReportLineFromRow($row)){
				fwrite($handle,$line);
				$result=true;
			}
			fclose($handle);
		}
		@unlink($tmpFile);
		return($result);
	}

	public function getUploadResponseRow(){
		return(
			array(
				"Timestamp"=>"",
				"Ack"=>"",
				"ShortMessage"=>"",
				"ErrorCode"=>"",
				"Value"=>"",
				"SKU"=>"",
				"ItemID"=>"",
				"CorrelationID"=>""
			)
		);
	}

	public function getUploadResponseFromRow($row){
		$result=false;
		if(strlen($row["Timestamp"])>0){
			$result="";
			$result.=strtotime($row["Timestamp"]).",";
			$result.=$this->quoteString($row["Ack"]).",";
			$result.=$this->quoteString($row["ShortMessage"]).",";
			$result.=$this->quoteString($row["ErrorCode"]).",";
			$result.=$this->quoteString($row["Value"]).",";
			$result.=$this->quoteString($row["SKU"]).",";
			$result.=$this->quoteString($row["ItemID"]).",";
			$result.=$this->quoteString($row["CorrelationID"])."\n";
		}
		return($result);
	}

	//Good Pull Parsing example: http://www.ibm.com/developerworks/xml/library/x-xmlphp2.html.
	public function convertUploadResponseToImportFile($task,$inputFile,$outputFile){
		$result=false;
		if(isset($php_errormsg)){
			unset($php_errormsg);
		}
		$tmpFile=realpath(dirname($inputFile))."/".rand(0,999999).".tmp";
		$this->validateLmsFile($inputFile,$tmpFile);
		@unlink($inputFile);
		$inputFile=$tmpFile;
		print("<h1>Validated the Import File - now a temp file called \"$inputFile\"</h1>");
		$reader = new XMLReader();
		$limit=500;
		$c=0;
		$orderFound=false;
		$reader->open($inputFile);
		$row=$this->getUploadResponseRow();
		$kill=false;
		$isValid=true;
		if($handle=fopen($outputFile,"w")){
			while($reader->read()){
//				if($reader->isValid()){
					switch($reader->nodeType){
						case(XMLREADER::ELEMENT):
							$keys=array_keys($row);
		//					print("Is ".$reader->localName." equal to OrderID.<br />");
							$nodeName=$reader->localName;
							if($nodeName=="Timestamp"){
								$row=$this->getUploadResponseRow();
							}
							if(in_array($nodeName,$keys)){
								$reader->read();
								$row[$nodeName]=$reader->value;
		//						print("<pre>");
		//						print_r($row);
		//						print("</pre>");
							}elseif($reader->localName==$task."Response"){
								if($orderFound){
									if($line=$this->getUploadResponseFromRow($row)){
										if(fwrite($handle,$line)===FALSE){
											$kill=true;
										}
									}
								}
								$orderFound=true;
							}
							break;
					}
					if($kill){
						break;
					}
					$c++;
//				}else{
//					$isValid=false;
//					$this->debug("The File Was Found to be Invalid",$reader->$php_errormsg);
//					break;
//				}
			}

			if(isset($php_errormsg)){
				$this->debug("Error Parsing XML File",$php_errormsg);
			}

//			if($isValid){
			if($line=$this->getUploadResponseFromRow($row)){
				fwrite($handle,$line);
				$result=true;
			}
//			}
			fclose($handle);
		}else{
			$this->debug("Error Opening Output File",$outputFile);
		}
		@unlink($tmpFile);
		return($result);
	}

	public static function convertToImportFile($task,$inputFile,$outputFile){
		$result=false;
		$lmsp=new LargeMerchantServiceParser();
		if($unzippedFile=$lmsp->unzipFile($inputFile,realpath(dirname($outputFile))."/",true)){
			$inputFile=$unzippedFile;
		}
		$inf=pathinfo($inputFile);
		if(strtolower($inf["extension"])=="xml"){
			switch($task){
				case "SoldReport":
					$result=$lmsp->convertSoldReportToImportFile($inputFile,$outputFile);
					break;
				case "ActiveInventoryReport":
					$result=$lmsp->convertActiveInventoryReportToImportFile($inputFile,$outputFile);
					break;
				case "VerifyReviseItem":
				case "ReviseItem":
				case "ReviseInventoryStatus":
				case "VerifyEndItem":
				case "EndItem":
				case "VerifyRelistItem":
				case "RelistItem":
				case "VerifyAddItem":
				case "AddItem":
					$result=$lmsp->convertUploadResponseToImportFile($task,$inputFile,$outputFile);
					break;
			}
		}else{
			$lmsp->addCustomError("0xLMPCI0", "File Type Error", "There is an error with the supplied file. It is not in the expected format.",array("task"=>$task,"inputFile"=>$inputFile,"outputFile"=>$outputFile),true);
		}
		return($result);
	}
}
?>